home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
muds
/
pennmush.000
/
pennmush-1.50-p8-linux.tar
/
pennmush
/
match.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-15
|
10KB
|
460 lines
/* match.c */
/* Routines for parsing arguments */
#include "copyright.h"
#include <ctype.h>
#include <string.h>
#include "config.h"
#include "db.h"
#include "externs.h"
#include "globals.h"
#include "match.h"
static dbref exact_match = NOTHING; /* holds result of exact match */
static int check_keys = 0; /* if non-zero, check for keys */
static dbref last_match = NOTHING; /* holds result of last match */
static int match_count; /* holds total number of inexact matches */
static dbref match_who; /* player who is being matched around */
static const char *match_name; /* name to match */
static int preferred_type = NOTYPE; /* preferred type */
#ifdef DO_GLOBALS
static int global = 0; /* when 0 -- normal match */
/* 1 -- global match */
/* 2 -- remote match */
#endif
char const *nomatch_message="I don't see that here.";
char const *ambiguous_message="I don't know which one you mean!";
/*
* check a list for objects that are prefix's for string, && are controlled
* || link_ok
*/
dbref pref_match(player, list, string)
dbref player;
dbref list;
const char *string;
{
dbref lmatch = NOTHING;
int mlen = 0;
while (list != NOTHING) {
if (string_prefix(string, db[list].name) && Puppet(list) &&
controls(player, list)) {
if (strlen(db[list].name) > mlen) {
lmatch = list;
mlen = strlen(db[list].name);
}
}
list = db[list].next;
}
return (lmatch);
}
void init_match(player, name, type)
dbref player;
const char *name;
int type;
{
exact_match = last_match = NOTHING;
match_count = 0;
match_who = player;
match_name = name;
check_keys = 0;
preferred_type = type;
#ifdef DO_GLOBALS
global = NORMAL_MATCH;
#endif
}
void init_match_check_keys(player, name, type)
dbref player;
const char *name;
int type;
{
init_match(player, name, type);
check_keys = 1;
}
#ifdef DO_GLOBALS
void init_match_global(player, name, type)
dbref player;
const char *name;
int type;
{
init_match(player, name, type);
global = GLOBAL_MATCH;
}
void init_match_global_check_keys(player, name, type)
dbref player;
const char *name;
int type;
{
init_match_global(player, name, type);
check_keys = 1;
}
void init_match_remote(location, name, type)
dbref location;
const char *name;
int type;
{
exact_match = last_match = NOTHING;
match_count = 0;
match_who = location;
match_name = name;
check_keys = 0;
preferred_type = type;
global = REMOTE_MATCH;
}
void init_match_remote_check_keys(location, name, type)
dbref location;
const char *name;
int type;
{
init_match_remote(location, name, type);
check_keys = 1;
}
#endif
static dbref choose_thing(thing1, thing2)
dbref thing1;
dbref thing2;
{
int has1;
int has2;
if (thing1 == NOTHING) {
return thing2;
} else if (thing2 == NOTHING) {
return thing1;
}
if (preferred_type != NOTYPE) {
if (Typeof(thing1) == preferred_type) {
if (Typeof(thing2) != preferred_type) {
return thing1;
}
} else if (Typeof(thing2) == preferred_type) {
return thing2;
}
}
if (check_keys) {
has1 = could_doit(match_who, thing1);
has2 = could_doit(match_who, thing2);
if (has1 && !has2) {
return thing1;
} else if (has2 && !has1) {
return thing2;
}
/* else fall through */
}
return (random() % 2 ? thing1 : thing2);
}
void match_player()
{
dbref match;
const char *p;
extern dbref short_page(); /* in bsd.c */
if (*match_name == LOOKUP_TOKEN) {
for (p = match_name + 1; isspace(*p); p++) ;
if ((match = lookup_player(p)) != NOTHING) {
exact_match = match;
} else {
/* try a partial match on a connected player, 2.0 style */
match = short_page(p);
if ((match != NOTHING) && (match != AMBIGUOUS))
exact_match = match;
}
}
}
/* returns nnn if name = #nnn, else NOTHING */
static dbref absolute_name()
{
dbref match;
if (*match_name == NUMBER_TOKEN) {
match = parse_dbref(match_name + 1);
if (match < 0 || match >= db_top) {
return NOTHING;
} else {
return match;
}
} else {
return NOTHING;
}
}
void match_absolute()
{
dbref match;
if ((match = absolute_name()) != NOTHING) {
exact_match = match;
}
}
void match_controlled_absolute()
{
/* this exists to provide mortals with a way of controlling their objects
* via dbref number, if they own the object. Unlike match_absolute(),
* here, a control check is done.
* alternatively, if the two objects are "nearby", the absolute
* match also succeeds. This allows players to get out of situations
* where there are several identically-named objects, and the game
* refuses to allow them to pick one by anything other than number.
*/
dbref match;
if (((match = absolute_name()) != NOTHING) &&
(controls(match_who, match) || nearby(match_who, match))) {
exact_match = match;
}
}
void match_me()
{
if (!strcasecmp(match_name, "me")) {
exact_match = match_who;
}
}
void match_here()
{
if (!strcasecmp(match_name, "here")
&& db[match_who].location != NOTHING) {
exact_match = db[match_who].location;
}
}
static void match_list(first)
dbref first;
{
dbref absolute;
absolute = absolute_name();
if (!controls(match_who, absolute))
absolute = NOTHING;
DOLIST(first, first) {
Access(first);
if (first == absolute) {
exact_match = first;
return;
} else if (!strcasecmp(db[first].name, match_name)) {
/* if there are multiple exact matches, randomly choose one */
exact_match = choose_thing(exact_match, first);
} else if (string_match(db[first].name, match_name)) {
last_match = first;
match_count++;
}
}
}
void match_possession()
{
match_list(db[match_who].contents);
}
void match_neighbor()
{
dbref loc;
loc = Location(match_who);
if (GoodObject(loc))
match_list(Contents(loc));
}
#ifdef DO_GLOBALS
void match_remote_contents()
{
if (match_who != NOTHING)
match_list(db[match_who].contents);
}
#endif
void match_container()
{
if (GoodObject(Location(match_who)))
match_list(Location(match_who));
}
void match_exit()
{
dbref loc;
dbref exit_tmp;
dbref absolute;
const char *match;
const char *p;
#ifdef DO_GLOBALS
switch (global) {
case NORMAL_MATCH:
loc = db[match_who].location;
break;
case GLOBAL_MATCH:
loc = MASTER_ROOM;
break;
case REMOTE_MATCH:
loc = match_who;
break;
}
#else
loc = db[match_who].location;
#endif
if (GoodObject(loc)) {
if (Typeof(loc) != TYPE_ROOM)
return;
absolute = absolute_name();
if (!controls(match_who, absolute))
absolute = NOTHING;
DOLIST(exit_tmp, db[loc].exits) {
Access(exit_tmp);
if (exit_tmp == absolute) {
exact_match = exit_tmp;
} else {
match = db[exit_tmp].name;
while (*match) {
/* check out this one */
for (p = match_name;
(*p
&& DOWNCASE(*p) == DOWNCASE(*match)
&& *match != EXIT_DELIMITER);
p++, match++) ;
/* did we get it? */
if (*p == '\0') {
/* make sure there's nothing afterwards */
while (isspace(*match))
match++;
if (*match == '\0' || *match == EXIT_DELIMITER) {
/* we got it */
exact_match = choose_thing(exact_match, exit_tmp);
goto next_exit; /* got this match */
}
}
/* we didn't get it, find next match */
while (*match && *match++ != EXIT_DELIMITER) ;
while (isspace(*match))
match++;
}
}
next_exit:
;
}
}
}
void match_everything()
{
match_me();
match_here();
match_absolute();
match_player();
if (match_result() == NOTHING) {
match_neighbor();
match_possession();
match_exit();
}
}
void match_nearby()
{
match_me();
match_here();
if (Long_Fingers(match_who)) {
match_absolute();
match_player();
} else
match_controlled_absolute();
if (match_result() == NOTHING) {
match_neighbor();
match_possession();
match_exit();
}
}
void match_near_things()
{
match_me();
if (Long_Fingers(match_who)) {
match_absolute();
match_player();
} else
match_controlled_absolute();
if (match_result() == NOTHING) {
match_neighbor();
match_possession();
}
}
#ifdef DO_GLOBALS
void match_remote()
{
match_exit();
match_remote_contents();
match_absolute();
match_player();
}
#endif
dbref match_result()
{
if (exact_match != NOTHING) {
return exact_match;
} else {
switch (match_count) {
case 0:
return NOTHING;
case 1:
return last_match;
default:
return AMBIGUOUS;
}
}
}
/* use this if you don't care about ambiguity */
dbref last_match_result()
{
if (exact_match != NOTHING) {
return exact_match;
} else {
return last_match;
}
}
dbref noisy_match_result()
{
dbref match;
switch (match = match_result()) {
case NOTHING:
notify(match_who, nomatch_message);
return NOTHING;
case AMBIGUOUS:
notify(match_who, ambiguous_message);
return NOTHING;
default:
return match;
}
}
dbref match_controlled(player, name)
dbref player;
const char *name;
{
dbref match;
init_match(player, name, NOTYPE);
match_everything();
match = noisy_match_result();
if (match != NOTHING && !controls(player, match)) {
notify(player, "Permission denied.");
return NOTHING;
} else {
return match;
}
}